package ro.pub.acs.android;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * In cadrul acestui tutorial vom folosi senzorul Sensor.TYPE_ORIENTATION.
 * Acest senzor ne ofera informatii cu privire la orientarea telefonului pe cele 3 directii.
 * 
 * Mai multe detalii despre lucrul cu senzorii puteti gasi in cartea:
 * Wrox Professional Android 2 Application Development
 * 
 * @author Vlad
 *
 */

/**
 *  * 1. Este necesar sa implementam interfata SensorEventListener, care contine semnaturile
 * metodelor ce vor fi apelate automat de catre sistemul Android.
 */
public class CompassOnScreen extends Activity implements SensorEventListener {
	
	//ne trebuie o referinta catre managerul de senzori
	private SensorManager sensorManager;
	
	//ne trebuie o referinta catre senzorul de orientare
	private Sensor sensor;
	
	//ne trebuie referinte catre elementele de tip TextView de pe ecran
	private TextView accuracyView;
	private TextView headingView;
	private TextView pitchView;
	private TextView rollView;

	//ne trebuie referinta catre elementul de tip ImageView de pe ecran
	private ImageView arrowView;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		//preluam referinte catre elementele de tip TextView de pe ecran
		accuracyView = (TextView)findViewById(R.id.accuracy);
		headingView = (TextView)findViewById(R.id.heading);
		pitchView = (TextView)findViewById(R.id.pitch);
		rollView = (TextView)findViewById(R.id.roll);

		//preluam referinta catre elementul de tip ImageView de pe ecran
		arrowView = (ImageView)findViewById(R.id.arrow);

		//tinem lumina ecranului aprinsa
		arrowView.setKeepScreenOn(true);

		//ne trebuie o referinta catre managerul de senzori
		sensorManager = (SensorManager)this.getApplicationContext().getSystemService(Context.SENSOR_SERVICE);

		//ne trebuie o referinta catre senzorul de orientare
		sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);

	}

	/** Dorim sa primim updateuri de la managerul de senzori doar daca activitatea curenta este vizibila */
	@Override
	protected void onResume() {
		super.onResume();
		//inregistram obiectul curent (this) ca listener pentru senzorul de orientare, cu  rata de refresh cea mai rapida.
		sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
	}

	/** Nu are rost sa primim updateuri de la managerul de senzori atunci cand activitatea curenta nu e vizibila */
	@Override
	protected void onPause() {
		super.onPause();
		sensorManager.unregisterListener(this);
	}

	/**
	 * Metoda este definita in interfata SensorEventListener.
	 * Metoda este apelata automat la o schimbare de acuratete.
	 */
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
			if (accuracy == SensorManager.SENSOR_STATUS_ACCURACY_LOW) {
				//afisam un mesaj corespunzator si in loguri, pentru a il vedea in perspectiva de debugging (DDMS)
				Log.d("NCIT", "ACCURACY LOW"); 
				accuracyView.setText("ACCURACY LOW");
				
			} else if (accuracy == SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM) {
				Log.d("NCIT", "ACCURACY MEDIUM");
				accuracyView.setText("ACCURACY MEDIUM");
				
			} else if (accuracy == SensorManager.SENSOR_STATUS_ACCURACY_HIGH) {
				Log.d("NCIT", "ACCURACY HIGH");
				accuracyView.setText("ACCURACY HIGH");
				
			} else if (accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
				Log.d("NCIT", "ACCURACY UNRELIABLE");
				accuracyView.setText("ACCURACY UNRELIABLE");
			}
		}
	}

	/**
	 * Metoda este definita in interfata SensorEventListener.
	 * Metoda este apelata automat la o schimbare de orientare.
	 */
	@Override
	public void onSensorChanged(SensorEvent sensorEvent) {
		if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
			float headingAngle = sensorEvent.values[0]; 
			float pitchAngle = sensorEvent.values[1]; 
			float rollAngle = sensorEvent.values[2];  

			Log.d("NCIT", "schimbare de orientare: " + headingAngle + " " + pitchAngle + " " + rollAngle);

			headingView.setText("Heading Angle: " + headingAngle);
			pitchView.setText("Pitch Angle: " + pitchAngle);
			rollView.setText("Roll Angle: " + rollAngle);

			//hai sa rotim sagetica pe ecran!

			//transformam imaginea din format DRAWABLE in format RAW pentru a putea fi prelucrata
			Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.arrow_img);

			//preluam inaltimea si latimea imaginii
			int w = bmp.getWidth();
			int h = bmp.getHeight();

			//setam corespunzator matricea pentru a efectua miscarea de rotatie
			//(detalii in anul 3 la EGC) :)
			Matrix mtx = new Matrix();
			mtx.postRotate(360-headingAngle); //setam in matrice cu cate grade dorim sa rotim imaginea

			//rotim imaginea initiala 
			Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, w, h, mtx, true);

			//transformam noua imagine din format RAW in format DRAWABLE pentru a putea fi afisata pe ecran
			BitmapDrawable bmd = new BitmapDrawable(rotatedBMP);

			//setam imaginea elementului de tip ImageView de pe ecran
			arrowView.setImageDrawable(bmd);
		}

	}
}